package com.imis.module.system.bus;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imis.base.constant.CommonConstant;
import com.imis.base.constant.enums.ArgumentResponseEnum;
import com.imis.base.globle.response.BaseResponse;
import com.imis.base.globle.response.CommonResponse;
import com.imis.base.util.ConvertUtils;
import com.imis.base.util.SerialCodeUtil;
import com.imis.module.base.BaseBus;
import com.imis.module.system.model.converter.SysOrganizationConverter;
import com.imis.module.system.model.po.SysOrganization;
import com.imis.module.system.model.po.SysUser;
import com.imis.module.system.model.ro.*;
import com.imis.module.system.model.vo.SysOrganizationTreeVO;
import com.imis.module.system.model.vo.SysOrganizationVO;
import com.imis.module.system.model.vo.SysUserOrganizationVO;
import com.imis.module.system.service.ISysOrganizationService;
import com.imis.module.system.service.ISysUserOrganizationService;
import com.imis.module.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 组织机构 业务处理类
 * </p>
 *
 * @author XinLau
 * @since 2020-04-22
 */
@Slf4j
@Service
public class SysOrganizationBus extends BaseBus {

    /**
     * 组织机构 服务类
     */
    private ISysOrganizationService serviceBySysOrganizationService;

    @Autowired
    public void setSysOrganizationService(ISysOrganizationService serviceBySysOrganizationService) {
        this.serviceBySysOrganizationService = serviceBySysOrganizationService;
    }

    /**
     * 系统用户 服务类
     */
    private ISysUserService serviceBySysUserService;

    @Autowired
    public void setServiceBySysUserService(ISysUserService serviceBySysUserService) {
        this.serviceBySysUserService = serviceBySysUserService;
    }

    /**
     * 用户-组织机构关联表 服务类
     */
    private ISysUserOrganizationService sysUserOrganizationService;

    @Autowired
    public void setSysUserOrganizationService(ISysUserOrganizationService sysUserOrganizationService) {
        this.sysUserOrganizationService = sysUserOrganizationService;
    }

    /**
     * 生成新的组织机构编号
     *
     * @param parentCode - 父级编码
     * @param parentId   - 父级编号
     * @return String[] - 组织机构编号
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/6/6 17:26
     */
    private String[] generateOrganizationCode(final String parentCode, final Long parentId) {
        // 1.根据父级组织机构编号查询子级组织机构
        List<SysOrganizationVO> sysOrganizationList = this.serviceBySysOrganizationService.selectSysOrganizationListByParentId(parentId == null ? 0 : parentId);
        String maxOrganizationCode = CommonConstant.EMPTY;
        // 2.1存在同级别组织机构
        if (sysOrganizationList.size() > 0) {
            maxOrganizationCode = sysOrganizationList.get(0).getOrganizationCode();
            for (SysOrganizationVO sysOrganization : sysOrganizationList) {
                int maxCode = Integer.parseInt(maxOrganizationCode.substring(maxOrganizationCode.length() - 2));
                String organizationCode = sysOrganization.getOrganizationCode();
                int code = Integer.parseInt(organizationCode.substring(organizationCode.length() - 2));
                if (code > maxCode) {
                    // 对比最值，确定最值
                    maxOrganizationCode = organizationCode;
                }
            }
        }
        // 生成   organizationCod
        String organizationCod = SerialCodeUtil.getSubSerialCode(parentCode, maxOrganizationCode);
        // 解析 organizationCod
        return SerialCodeUtil.cuttingSerialCode(organizationCod);
    }

    /**
     * 添加组织机构重复校验
     *
     * @param sysOrganizationAdd - 组织机构添加
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/9 9:47
     */
    private SysOrganization organizationAddVerification(final SysOrganizationAddRO sysOrganizationAdd) {
        // 1.父级ID存在校验
        Long parentId = sysOrganizationAdd.getParentId();
        String parentOrganizationCode = CommonConstant.EMPTY;
        if (ConvertUtils.isNotEmpty(parentId) && parentId != 0) {
            SysOrganization sysOrganizationParent = this.serviceBySysOrganizationService.getById(parentId);
            // 1.根据父级父级组织机构信息查询，该父级父级组织机构名不存在
            ArgumentResponseEnum.ORGANIZATION_ADD_ERR_PARENT_NON.assertNotNull(sysOrganizationParent, sysOrganizationParent.getOrganizationName());
            // 2.根据父级父级组织机构信息查询，该父级父级组织机构被删除
            ArgumentResponseEnum.ORGANIZATION_ADD_ERR_PARENT_DELETE.assertIsTrue(CommonConstant.DEL_FLAG_NOT_DELETE.equals(sysOrganizationParent.getDelFlag()), sysOrganizationParent.getOrganizationName());
            parentOrganizationCode = sysOrganizationParent.getOrganizationCode();
        }
        // 2. 组织机构存在校验
        SysOrganization sysOrganization = this.serviceBySysOrganizationService.queryOrganizationByName(sysOrganizationAdd.getOrganizationName());
        if (ConvertUtils.isNotEmpty(sysOrganization)) {
            // 1.根据组织机构信息查询，该组织机构被删除
            ArgumentResponseEnum.ORGANIZATION_ADD_ERR_DELETE.assertIsTrue(CommonConstant.DEL_FLAG_NOT_DELETE.equals(sysOrganization.getDelFlag()), sysOrganization.getOrganizationName());
            // 2.根据组织机构信息查询，该组织机构名存在
            ArgumentResponseEnum.ORGANIZATION_ADD_ERR_REPEAT.assertIsNull(sysOrganization, sysOrganization.getOrganizationName());
        }
        // 3.生成组织机构编号（生成多个，只取最后一个使用）
        String[] organizationCodSpecimen = this.generateOrganizationCode(parentOrganizationCode, parentId);
        String organizationCod = organizationCodSpecimen[organizationCodSpecimen.length - 1];
        // 校验是否生成成功
        ArgumentResponseEnum.ORGANIZATION_ADD_ERR_PARENT_NON.assertNotEmpty(organizationCod);
        return SysOrganizationConverter.INSTANCE.getAddEntity(sysOrganizationAdd, organizationCod);
    }

    /**
     * 删除组织机构校验
     *
     * @param organizationIdentification - 组织机构对象编号
     * @return SysOrganization - 组织机构
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    private SysOrganization organizationDeleteVerification(final Long organizationIdentification) {
        SysOrganization sysOrganization = this.serviceBySysOrganizationService.getById(organizationIdentification);
        // 1.根据组织机构信息查询，判断组织机构是否存在
        ArgumentResponseEnum.ORGANIZATION_DELETE_ERR_NON.assertNotNull(sysOrganization, organizationIdentification);
        // 2.判断组织机构是否分配
        Long[] sysUserIdArray = this.serviceBySysOrganizationService.queryUserIdentificationByOrganizationIdentification(sysOrganization.getId());
        ArgumentResponseEnum.ORGANIZATION_DELETE_ERR_ASSIGNED.assertIsNull(sysUserIdArray, Arrays.toString(sysUserIdArray));
        // 3.判断组织机构旗下是否存在子级组织机构
        List<SysOrganizationVO> sysOrganizationChildList = this.serviceBySysOrganizationService.selectSysOrganizationListByParentId(sysOrganization.getId());
        ArgumentResponseEnum.ORGANIZATION_DELETE_ERR_HAVE_CHILD.assertIsNull(sysOrganizationChildList, sysOrganization.getOrganizationName());
        return sysOrganization;
    }

    /**
     * 组织机构更新校验
     *
     * @param sysOrganizationUpdate - 组织机构更新对象
     * @return SysOrganization -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    private SysOrganization organizationUpdateVerification(final SysOrganizationUpdateRO sysOrganizationUpdate) {
        SysOrganization sysOrganization = this.serviceBySysOrganizationService.getById(sysOrganizationUpdate.getId());
        // 1.根据组织机构信息查询，该组织机构不存在
        ArgumentResponseEnum.ORGANIZATION_UPDATE_ERR_NON.assertNotNull(sysOrganization, sysOrganizationUpdate.getOrganizationName());
        // 2.组织机构名重复校验
        if (!sysOrganization.getOrganizationName().equals(sysOrganizationUpdate.getOrganizationName())) {
            SysOrganization sysOrganizationByName = this.serviceBySysOrganizationService.queryOrganizationByName(sysOrganizationUpdate.getOrganizationName());
            ArgumentResponseEnum.ORGANIZATION_UPDATE_ERR_REPEAT.assertIsNull(sysOrganizationByName, sysOrganizationByName.getOrganizationName());
        }
        SysOrganizationConverter.INSTANCE.getUpdateEntity(sysOrganization, sysOrganizationUpdate);
        return sysOrganization;
    }

    /**
     * 用户授权组织机构校验
     *
     * @param sysGrantOrganizationToUser - 用户授权组织机构
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    private Boolean grantOrganizationToUserVerification(final SysGrantOrganizationToUserRO sysGrantOrganizationToUser) {
        // 1.验证用户合法性
        Long userId = sysGrantOrganizationToUser.getUserId();
        SysUser sysUser = this.serviceBySysUserService.getById(userId);
        ArgumentResponseEnum.GRANT_ORGANIZATION_TO_USER_ERR_NON_USER.assertNotNull(sysUser, userId);
        // 2.验证组织机构合法性
        List<SysOrganizationResponsibleRO> sysOrganizationResponsibleList = sysGrantOrganizationToUser.getOrganizationIdList();
        ArgumentResponseEnum.GRANT_ORGANIZATION_TO_USER_ERR_NON_ORGANIZATION.assertNotEmpty(sysOrganizationResponsibleList, sysOrganizationResponsibleList.toString());
        List<Long> organizationIdList = new ArrayList<>();
        for (SysOrganizationResponsibleRO sysOrganizationResponsible : sysOrganizationResponsibleList) {
            organizationIdList.add(sysOrganizationResponsible.getOrganizationId());
        }
        // 3.验证组织机构数量匹配
        List<SysOrganization> sysOrganizationList = this.serviceBySysOrganizationService.listByIds(organizationIdList);
        ArgumentResponseEnum.GRANT_ORGANIZATION_TO_USER_ERR_NON_ORGANIZATION.assertNotEmpty(sysOrganizationList, organizationIdList.toString());
        return Boolean.TRUE;
    }

    /**
     * 组织机构分配用户校验
     *
     * @param sysGrantUserToOrganization - 组织机构分配用户
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    private Boolean authorizingUserToOrganizationVerification(final SysGrantUserToOrganizationRO sysGrantUserToOrganization) {
        // 1.验证组织机构合法性
        Long organizationId = sysGrantUserToOrganization.getOrganizationId();
        SysOrganization sysOrganization = this.serviceBySysOrganizationService.getById(organizationId);
        ArgumentResponseEnum.AUTHORIZING_USER_TO_ORGANIZATION_NON_ORGANIZATION.assertNotNull(sysOrganization, organizationId);
        // 2.验证用户合法性
        List<SysUserResponsibleOrganizationRO> sysUserResponsibleOrganizationList = sysGrantUserToOrganization.getUserIdList();
        ArgumentResponseEnum.AUTHORIZING_USER_TO_ORGANIZATION_NON_USER.assertNotEmpty(sysUserResponsibleOrganizationList, sysUserResponsibleOrganizationList.toString());
        List<Long> userIdList = new ArrayList<>();
        for (SysUserResponsibleOrganizationRO sysUserResponsibleOrganization : sysUserResponsibleOrganizationList) {
            userIdList.add(sysUserResponsibleOrganization.getUserId());
        }
        // 3.验证用户数量匹配
        List<SysUser> sysUserList = this.serviceBySysUserService.listByIds(userIdList);
        ArgumentResponseEnum.AUTHORIZING_USER_TO_ORGANIZATION_NON_USER.assertNotEmpty(sysUserList, userIdList.toString());
        return Boolean.TRUE;
    }

    /**
     * 组织机构取消分配用户
     *
     * @param sysGrantUserToOrganization - 组织机构分配用户
     * @return Boolean -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    private Boolean unAuthorizingUserToOrganizationVerification(final SysGrantUserToOrganizationRO sysGrantUserToOrganization) {
        return this.authorizingUserToOrganizationVerification(sysGrantUserToOrganization);
    }

    /**
     * 分页查询组织机构
     *
     * @param pagingQueryOrganizationDTO - 组织机构查询对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public CommonResponse<Page<SysOrganizationTreeVO>> pagingQuerySysOrganizationParentListByParameter(final PagingQueryOrganizationDTO pagingQueryOrganizationDTO) {
        Page<SysOrganizationTreeVO> sysMenuParentListByParameter = this.serviceBySysOrganizationService.pagingQuerySysOrganizationParentListByParameter(pagingQueryOrganizationDTO);
        return new CommonResponse<>(sysMenuParentListByParameter);
    }

    /**
     * 查询组织机构树接口
     *
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public CommonResponse<List<SysOrganizationTreeVO>> querySysOrganizationTreeList() {
        List<SysOrganizationTreeVO> sysOrganizationTreeVOList = this.serviceBySysOrganizationService.querySysOrganizationTreeList();
        return new CommonResponse<>(sysOrganizationTreeVOList);
    }

    /**
     * 组织机构添加
     *
     * @param sysOrganizationAdd - 组织机构添加对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public BaseResponse addOrganization(final SysOrganizationAddRO sysOrganizationAdd) {
        // 1.校验组织机构名重复
        SysOrganization sysOrganization = this.organizationAddVerification(sysOrganizationAdd);
        // 保存组织机构编
        boolean saveOrganization = this.serviceBySysOrganizationService.save(sysOrganization);
        // 2.判断保存成功
        ArgumentResponseEnum.ORGANIZATION_ADD_ERR.assertIsTrue(saveOrganization, sysOrganizationAdd.getOrganizationName());
        return new CommonResponse<>();
    }

    /**
     * 组织机构删除
     *
     * @param organizationIdentification - 组织机构标识
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public BaseResponse deleteOrganization(final Long organizationIdentification) {
        // 1.删除组织机构校验
        SysOrganization sysOrganization = this.organizationDeleteVerification(organizationIdentification);
        // 2.删除组织机构
        boolean deleteOrganization = this.serviceBySysOrganizationService.deleteOrganizationById(organizationIdentification);
        // 3.判断删除成功
        ArgumentResponseEnum.ORGANIZATION_DELETE_ERR.assertIsTrue(deleteOrganization, sysOrganization.getOrganizationName());
        return new CommonResponse<>();
    }

    /**
     * 组织机构查看
     *
     * @param organizationIdentification - 组织机构标识
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public CommonResponse<SysOrganizationVO> queryOrganizationById(final Long organizationIdentification) {
        SysOrganization sysOrganization = this.serviceBySysOrganizationService.getById(organizationIdentification);
        // 1.根据组织机构信息查询，该组织机构不存在
        ArgumentResponseEnum.ORGANIZATION_QUERY_ERR.assertNotNull(sysOrganization, organizationIdentification);
        return new CommonResponse<>(SysOrganizationConverter.INSTANCE.getReturnValue(sysOrganization));
    }

    /**
     * 组织机构更新
     *
     * @param sysOrganizationUpdate - 组织机构更新对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public BaseResponse updateOrganization(final SysOrganizationUpdateRO sysOrganizationUpdate) {
        // 1.更新组织机构校验
        SysOrganization sysOrganization = this.organizationUpdateVerification(sysOrganizationUpdate);
        // 2.组织机构更新
        boolean updateOrganization = this.serviceBySysOrganizationService.updateByOrganizationIdentification(sysOrganization);
        // 3.判断保存成功
        ArgumentResponseEnum.ORGANIZATION_UPDATE_ERR.assertIsTrue(updateOrganization, sysOrganizationUpdate.getOrganizationName());
        return new CommonResponse<>();
    }

    /**
     * 根据父组织机构ID查询组织机构树接口
     *
     * @param parentId - 父组织机构ID
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public CommonResponse<List<SysOrganizationTreeVO>> queryOrganizationTreeByParentId(final Long parentId) {
        // 父级组织机构校验
        SysOrganization parentSysOrganization = this.serviceBySysOrganizationService.getById(parentId);
        ArgumentResponseEnum.ORGANIZATION_TREE_QUERY_ERR_NON_PARENT.assertNotNull(parentSysOrganization, parentId);
        //  查询组织机构树
        List<SysOrganizationTreeVO> sysOrganizationTreeVOList = this.serviceBySysOrganizationService.queryOrganizationTreeByParent(parentSysOrganization);
        return new CommonResponse<>(sysOrganizationTreeVOList);
    }

    /**
     * 根据用户ID查询用户拥有的组织机构树接口
     *
     * @param userIdentification - 用户唯一标识
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public CommonResponse<List<SysUserOrganizationVO>> queryOrganizationByUserIdentification(final Long userIdentification) {
        // 1.用户合法性判断
        SysUser sysUser = this.serviceBySysUserService.getById(userIdentification);
        ArgumentResponseEnum.ORGANIZATION_TREE_QUERY_ERR_NON_USER.assertNotNull(sysUser, userIdentification);
        // 2.查询用户组织机构
        List<SysUserOrganizationVO> sysUserOrganizationVOList = this.serviceBySysOrganizationService.queryOrganizationByUserIdentification(sysUser.getId());
        return new CommonResponse<>(sysUserOrganizationVOList);
    }

    /**
     * 用户授权组织机构
     *
     * @param sysGrantOrganizationToUser - 用户授权组织机构
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public BaseResponse grantOrganizationToUser(SysGrantOrganizationToUserRO sysGrantOrganizationToUser) {
        // 1.为用户授权组织机构校验
        boolean aBoolean = this.grantOrganizationToUserVerification(sysGrantOrganizationToUser);
        ArgumentResponseEnum.GRANT_ORGANIZATION_TO_USER_ERR.assertIsTrue(aBoolean, sysGrantOrganizationToUser.getUserId());
        // 2.授权操作
        boolean grant = this.serviceBySysOrganizationService.grantOrganizationToUser(sysGrantOrganizationToUser);
        ArgumentResponseEnum.GRANT_ORGANIZATION_TO_USER_ERR.assertIsTrue(grant, sysGrantOrganizationToUser.getUserId());
        return new CommonResponse<>();
    }

    /**
     * 取消用户组织机构授权
     *
     * @param userIdentification - 用户唯一标识
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public BaseResponse terminateAllOrganizationToUser(final Long userIdentification) {
        // 1.验证用户存在
        SysUser sysUser = this.serviceBySysUserService.getById(userIdentification);
        ArgumentResponseEnum.TERMINATE_ALL_ORGANIZATION_TO_USER_ERR_NON_USER.assertNotNull(sysUser, userIdentification);
        // 2.撤销授权
        boolean terminate = this.serviceBySysOrganizationService.terminateAllOrganizationToUser(sysUser.getId());
        ArgumentResponseEnum.TERMINATE_ALL_ORGANIZATION_TO_USER_ERR.assertIsTrue(terminate, sysUser.getId());
        return new CommonResponse<>();
    }

    /**
     * 组织机构分配用户
     *
     * @param sysGrantUserToOrganization - 组织机构分配用户
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/7/20 9:18
     */
    public BaseResponse authorizingUserToOrganization(final SysGrantUserToOrganizationRO sysGrantUserToOrganization) {
        // 1.组织机构分配用户校验
        boolean aBoolean = this.authorizingUserToOrganizationVerification(sysGrantUserToOrganization);
        ArgumentResponseEnum.GRANT_ORGANIZATION_TO_USER_ERR.assertIsTrue(aBoolean, sysGrantUserToOrganization.getOrganizationId());
        // 2.授权操作
        boolean grant = this.sysUserOrganizationService.authorizingUserToOrganization(sysGrantUserToOrganization);
        ArgumentResponseEnum.AUTHORIZING_USER_TO_ORGANIZATION_ERR.assertIsTrue(grant, sysGrantUserToOrganization.getOrganizationId());
        return new CommonResponse<>();
    }

    /**
     * 组织机构取消分配用户
     *
     * @param sysGrantUserToOrganization - 组织机构分配用户
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/7/20 9:18
     */
    public BaseResponse unAuthorizingUserToOrganization(final SysGrantUserToOrganizationRO sysGrantUserToOrganization) {
        // 1.组织机构取消分配用户
        boolean aBoolean = this.unAuthorizingUserToOrganizationVerification(sysGrantUserToOrganization);
        ArgumentResponseEnum.GRANT_ORGANIZATION_TO_USER_ERR.assertIsTrue(aBoolean, sysGrantUserToOrganization.getOrganizationId());
        // 2.取消授权操作
        boolean terminate = this.sysUserOrganizationService.unAuthorizingUserToOrganization(sysGrantUserToOrganization);
        ArgumentResponseEnum.UN_AUTHORIZING_USER_TO_ORGANIZATION_ERR.assertIsTrue(terminate, sysGrantUserToOrganization.getOrganizationId());
        return new CommonResponse<>();
    }

}